//
//  XLConversationInputView.m
//  XLConversationInputViewDemo
//
//  Created by ilongge on 2022/8/2.
//

#define kXLCIToolBarHeight     49
#define kXLCIAnimationDuration 0.25

#import "XLConversationInputView.h"
#import "XLCvstInputMoreItemView.h"
#import "XLEmojiInputView.h"
#import "XLCIViewResourcesManager.h"
#import "XLConversationInputToolbar.h"
#import "XLConversationInputViewDef.h"
#import "XLEmojiManager.h"
#import "XLFileListViewController.h"
#import "XLConversationInputVoiceRecordView.h"
#import "XLCvstInputMoreItemModel.h"
  
//static JFCloudChatUIKit *kit = nil;


@interface XLConversationInputView()
<
XLCIFileTypeProtocol,
XLCIAudioRecorderProtocol
>

@property (nonatomic, strong) XLEmojiInputView *emojiInput;
@property (nonatomic, strong) XLConversationInputToolbar *toolBar;
@property (nonatomic, strong) XLCvstInputMoreItemView *moreItemActionView;
@property (nonatomic, strong) XLConversationInputVoiceRecordView *recoredPressView;
@property (nonatomic, strong) XLCvstInputMoreItemModel *selectMoreItem;
@property (nonatomic, assign) CGFloat moreItemViewHeight;
@property (nonatomic, assign) CGFloat topMargin;
@property (nonatomic, assign) CGFloat moreItemViewMinimumInteritemSpacingt;
@property (nonatomic, weak) id <XLConversationInputViewProtocol> delegate;
@property (nonatomic, copy) void(^selectPhotosHandler)(NSArray<UIImage *> *images);
@property (nonatomic, copy) void(^selectVideoHandler)(NSDictionary *videoInfo);
@property (nonatomic, assign) BOOL keyboardShow;
@end

@implementation XLConversationInputView

#pragma mark ------------------------- Public
- (instancetype)initWithViewController:(UIViewController <XLConversationInputViewProtocol> *)viewController
{
    _topMargin = 0;
    UIView *superView = viewController.view.superview;
    CGRect viewFrame = viewController.view.frame;
    _topMargin = viewFrame.origin.y;
    UIWindow *windows = [[UIApplication sharedApplication] keyWindow];
    if (superView == nil) {
        if (viewController.navigationController && viewController.navigationController.isNavigationBarHidden == NO) {
            _topMargin = kXLCINaviHeight;
        }
    }
    else{
        while (superView) {
            viewFrame = [superView convertRect:viewFrame toView:windows];
            superView = superView.superview;
            _topMargin = viewFrame.origin.y;
        }
    }
    CGRect frame = CGRectMake(0,
                              kXLCISCREEN_HEIGHT - kXLCIToolBarHeight - kXLCIBottomSafeHeight - _topMargin,
                              kXLCISCREEN_WIDTH,
                              kXLCIToolBarHeight);
    self = [super initWithFrame:frame];
    if (self) {
        _delegate = viewController;
        _maxVoiceDuration = 60.f;
        _minVoiceDuration = 2.0f;
        _maxMessageTextLength = 1000;
    }
    return self;
}

- (void)showInputView
{
    [self initData];
    [self initSubviews];
}

- (void)insertAtSomeoneText:(NSString *)atText
{
    self.toolBar.messageTextView.text = [self.toolBar.messageTextView.text stringByReplacingCharactersInRange:self.toolBar.messageTextView.selectedRange
                                                                                                   withString:atText];
    self.toolBar.messageTextView.selectedRange = NSMakeRange(self.toolBar.messageTextView.selectedRange.location+atText.length,
                                                             self.toolBar.messageTextView.selectedRange.length);
}


-(void)setDisable:(BOOL)disable andMessage:(NSString *)message
{
    self.toolBar.messageTextView.text = message;
    if (disable){
        self.userInteractionEnabled = NO;
        [self keyboardWillHide:nil];
    }
    else{
        self.userInteractionEnabled = YES;
        [self.toolBar textViewTextDidChange];
    }
}

-(void)enableKeyboardNotification:(BOOL)enable
{
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillShowNotification
                                                  object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillHideNotification
                                                  object:nil];
    if (enable){
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillShow:)
                                                     name:UIKeyboardWillShowNotification
                                                   object:nil];
        
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(keyboardWillHide:)
                                                     name:UIKeyboardWillHideNotification
                                                   object:nil];
    }
}

- (NSString *)messageText
{
    return self.toolBar.messageTextView.text;
}

#pragma mark ------------------------- Private

/// 初始化数据
- (void)initData {
    
    NSArray *supportMoreItems;
    if (self.delegate && [self.delegate respondsToSelector:@selector(supportMoreItem)]) {
        supportMoreItems = [self.delegate supportMoreItem];
    }
    for (NSInteger index = 0; index < supportMoreItems.count; index++) {
        XLCvstInputMoreItemModel *item = supportMoreItems[index];
        NSString *string = [[NSString stringWithFormat:@"%p", item] substringFromIndex:2];
        long sum = 0;
        long add = 1;
        for (NSInteger i = string.length-2; i >= 0; i -= 2) {
            NSString *subStr = [string substringWithRange:NSMakeRange(i,  2)];
            long number = strtoul([subStr UTF8String],  0,  16);
            number =  number * add;
            sum = sum + number;
            add = add * 256;
        }
    }
    CGFloat maxWidth = self.frame.size.width - 70;
    NSInteger col = 3;
    NSInteger retCol = col;
    CGFloat margin = (maxWidth - ItemWidth * col) / (col-1);
    CGFloat retMargin = margin;
    while (margin > 15) {
        retMargin = margin;
        retCol = col;
        col ++ ;
        margin = (maxWidth - ItemWidth * col) / (col-1);
    }
    
    self.moreItemViewMinimumInteritemSpacingt = retMargin;
    self.moreItemActionView = [[XLCvstInputMoreItemView alloc] initWithFrame:CGRectZero
                                                            supportMoreItems:supportMoreItems];
    self.moreItemActionView.hidden = YES;
    
    WeakSelf(weakSelf);
    self.moreItemActionView.clickItemHandler = ^(XLCvstInputMoreItemModel * item) {
        StrongSelf(strongSelf);
        [strongSelf moreItemActionFor:item];
    };
    
    NSInteger row = (self.moreItemActionView.itemCounts + (retCol - 1)) / retCol;
    if (row > 3) {
        row = 3;
    }
    self.moreItemViewHeight = row * ItemHeight + (row-1) * ItemLineMargin + 40;
}

- (void)initSubviews {
    self.layer.backgroundColor = [UIColor colorWithRed:247/255.0 green:247/255.0 blue:247/255.0 alpha:1].CGColor;
    self.clipsToBounds = YES;
    [self configToolBar];
    [self configRecoredView];
}

- (void)configToolBar
{
    self.toolBar = [[XLConversationInputToolbar alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, kXLCIToolBarHeight)];
    self.toolBar.maxMessageTextLength = self.maxMessageTextLength;
    [self addSubview:self.toolBar];
    WeakSelf(weakSelf);
    self.toolBar.messageTextHeightChangedBlock = ^(CGFloat height) {
        StrongSelf(strongSelf);
        CGRect rect = strongSelf.frame;
        if (rect.size.height > height) {
            [strongSelf delMoreItemViewToBoard];
        }
        if (height != rect.size.height) {
            rect.origin.y -= height - rect.size.height;
            rect.size.height = height;
            [strongSelf changeSelfFrame:rect
                               duration:kXLCIAnimationDuration
                             completion:nil];
        }
    };
    
    self.toolBar.addMoreItemActionBlock = ^(BOOL isSelected) {
        StrongSelf(strongSelf);
        [strongSelf addMoreItemAction:isSelected];
    };
    
    self.toolBar.sendMessageBlock = ^(XLCvstInputMoreItemModel *item, NSString *message) {
        StrongSelf(strongSelf);
        strongSelf.selectMoreItem = item;
        [strongSelf processMessageString:message];
    };
    
    self.toolBar.voiceIconButtonBlock = ^(BOOL isSelected) {
        StrongSelf(strongSelf);
        if (isSelected){
            [strongSelf.recoredPressView returnToStart];
            [[[UIApplication sharedApplication] delegate].window addSubview:strongSelf.recoredPressView];
        }
        else{
            [strongSelf.recoredPressView removeFromSuperview];
        }
    };
    
    self.toolBar.layoutSubviewsBlock = ^ {
        StrongSelf(strongSelf);
        CGRect rect = [strongSelf.toolBar.messageTextBackgorundView convertRect:strongSelf.toolBar.recordAudioButton.frame
                                                                         toView:strongSelf];
        CGFloat minX = CGRectGetMinX(rect);
        CGFloat width = CGRectGetWidth(strongSelf.toolBar.recordAudioButton.frame);
        rect = [strongSelf.superview convertRect:strongSelf.frame toView:strongSelf.window];
        rect = CGRectMake(minX,
                          rect.origin.y,
                          width,
                          strongSelf.toolBar.frame.size.height);
        strongSelf.recoredPressView.frame = rect;
    };
    
    self.toolBar.atSomeoneBlock = ^BOOL(XLCvstInputMoreItemModel *item, NSString *name) {
        StrongSelf(strongSelf);
        if ([strongSelf checkConversationInputViewProtocol]) {
            return [strongSelf.delegate selectCompleteWithItem:item andValue:name];
        }
        return NO;
    };
}

- (void)addMoreItemAction:(BOOL)isSelected
{
    if (isSelected) {
        [self addMoreItemViewToBoard];
    }
    else{
        [self delMoreItemViewToBoard];
    }
}
- (void)reloadInputViews
{
    
}

- (void)configRecoredView
{
    NSString *audioRecorderCachesDirectory;
    if (self.delegate && [self.delegate respondsToSelector:@selector(audioRecorderCachesDirectory)]) {
        audioRecorderCachesDirectory = [self.delegate audioRecorderCachesDirectory];
    }
    self.recoredPressView = [[XLConversationInputVoiceRecordView alloc] initWithRootPath:audioRecorderCachesDirectory];
    self.recoredPressView.maxVoiceDuration = self.maxVoiceDuration;
    self.recoredPressView.minVoiceDuration = self.minVoiceDuration;
    self.recoredPressView.delegate = self;
    WeakSelf(weakSelf);
    self.recoredPressView.audioRecordCompleteBlock = ^(XLCvstInputMoreItemModel *item, NSURL *recordFileUrl) {
        StrongSelf(strongSelf);
        strongSelf.selectMoreItem = item;
        if ([strongSelf checkConversationInputViewProtocol]) {
            NSDictionary *valueData;
            if ([recordFileUrl.scheme isEqualToString:@"error"]) {
                NSString *value = [recordFileUrl.description stringByReplacingOccurrencesOfString:@"error://"
                                                                                       withString:@""];
                if ([value isEqualToString:@"durationTooShort"]) {
                    NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain
                                                         code:-1111
                                                     userInfo:@{NSLocalizedDescriptionKey:@"Record_Durarion_Too_Short"}];
                    valueData = @{@"error":error};
                }
                else{
                    NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain
                                                         code:-9999
                                                     userInfo:@{NSLocalizedDescriptionKey:@"Record_Failed"}];
                    valueData = @{@"error":error};
                }
            }
            else if (recordFileUrl.path.length) {
                valueData = @{@"recordFileUrl":recordFileUrl};
            }
            else{
                NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain
                                                     code:-9999
                                                 userInfo:@{NSLocalizedDescriptionKey:@"Record_Failed"}];
                valueData = @{@"error":error};
            }
            [strongSelf.delegate selectCompleteWithItem:strongSelf.selectMoreItem andValue:valueData];
        }
    };
}
- (void)rebackToInputText
{
    if (self.toolBar.voiceIconButton.isSelected) {
        [self.toolBar voiceIconButtonAction:self.toolBar.voiceIconButton];
    }
}

#pragma mark ------------------------- 键盘弹起

- (void)keyboardWillShow:(NSNotification *)notification
{
    if (self.keyboardShow == NO) {
        [self delMoreItemViewToBoard];
    }
    CGRect endFrame = [notification.userInfo[@"UIKeyboardFrameEndUserInfoKey"] CGRectValue];
    CGFloat XLCIToolBarHeight = kXLCIToolBarHeight>self.toolBar.frame.size.height?kXLCIToolBarHeight:self.toolBar.frame.size.height;
    CGRect rect = CGRectMake(0,
                             kXLCISCREEN_HEIGHT - endFrame.size.height - XLCIToolBarHeight - _topMargin,
                             kXLCISCREEN_WIDTH,
                             XLCIToolBarHeight);
    NSTimeInterval duration = [notification.userInfo[@"UIKeyboardAnimationDurationUserInfoKey"] doubleValue];
    [self changeSelfFrame:rect
                 duration:duration
               completion:nil];
    self.keyboardShow = YES;
}

- (void)keyboardWillHide:(NSNotification *)notification
{
    if (self.keyboardShow == NO) {
        [self delMoreItemViewToBoard];
    }
    CGFloat XLCIToolBarHeight = kXLCIToolBarHeight>self.toolBar.frame.size.height?kXLCIToolBarHeight:self.toolBar.frame.size.height;
    CGRect rect = CGRectMake(0,
                             kXLCISCREEN_HEIGHT - XLCIToolBarHeight - kXLCIBottomSafeHeight - _topMargin,
                             kXLCISCREEN_WIDTH,
                             XLCIToolBarHeight);
    NSTimeInterval duration = [notification.userInfo[@"UIKeyboardAnimationDurationUserInfoKey"] doubleValue];
    [self changeSelfFrame:rect
                 duration:duration
               completion:nil];
    self.keyboardShow = NO;
}

#pragma mark ------------------------- 变换 frame
- (void)changeSelfFrame:(CGRect)frame duration:(NSTimeInterval)duration completion:(void(^)(void))completion
{
    if ((self.frame.size.height != frame.size.height
         ||
         self.frame.origin.y != frame.origin.y)
        &&
        duration > 0.0) {
        
        if (self.inputViewRectBlock) {
            self.inputViewRectBlock(frame, duration);
        }
        [UIView animateWithDuration:duration
                         animations:^{
            self.frame = frame;
        }
                         completion:^(BOOL finished) {
            if (finished) {
                if (completion) {
                    completion();
                }
            }
        }];
        CGRect toolbarRect = CGRectMake(0, CGRectGetMaxY(self.toolBar.frame), self.frame.size.width, self.moreItemViewHeight);
        self.moreItemActionView.frame = toolbarRect;
    }
}

- (void)addMoreItemViewToBoard {
    CGRect toolbarRect = CGRectMake(0, CGRectGetMaxY(self.toolBar.frame), self.frame.size.width, self.moreItemViewHeight);
    self.moreItemActionView.frame = toolbarRect;
    self.moreItemActionView.hidden = NO;
    self.moreItemActionView.minimumInteritemSpacing = self.moreItemViewMinimumInteritemSpacingt;
    if (self.moreItemActionView.superview == nil) {
        [self addSubview:self.moreItemActionView];
    }
    CGRect rect = self.frame;
    rect.origin.y -= self.moreItemViewHeight;
    rect.size.height += self.moreItemViewHeight;
    [self changeSelfFrame:rect
                 duration:kXLCIAnimationDuration
               completion:nil];
}

- (void)delMoreItemViewToBoard {
    if (self.moreItemActionView.superview) {
        CGRect moreRect = [self convertRect:self.moreItemActionView.frame toView:self.superview];
        CGFloat maxY = self.superview.frame.size.height - self.moreItemViewHeight;
        if (moreRect.origin.y < maxY) {
            CGRect rect = self.frame;
            rect.origin.y += self.moreItemViewHeight;
            rect.size.height -= self.moreItemViewHeight;
            self.moreItemActionView.hidden = YES;
            [self changeSelfFrame:rect
                         duration:kXLCIAnimationDuration
                       completion:nil];
        }
    }
}

+ (UIImage *)imageWithColor:(UIColor *)aColor withFrame:(CGRect)aFrame{
    UIGraphicsBeginImageContext(aFrame.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [aColor CGColor]);
    CGContextFillRect(context, aFrame);
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

#pragma mark ------------------------- MoreItem

- (void)moreItemActionFor:(XLCvstInputMoreItemModel *)item {
    self.selectMoreItem = item;
    if ([self checkConversationInputViewProtocol]) {
        [self.delegate selectCompleteWithItem:self.selectMoreItem andValue:nil];
    }
    [self.toolBar addMoreItemButtonAction:self.toolBar.addMoreItemButton];
}

- (void)moreItemAcitonFile:(void (^)(NSArray<NSDictionary *> *files))selectFilesHandler
{
    XLFileListViewController *fileList = [[XLFileListViewController alloc] init];
    fileList.delegate = self;
    fileList.sendFileBlock = selectFilesHandler;
    UINavigationController *navi = [self creatNaviWithRootController:fileList];
    UIWindow *window = [[UIApplication sharedApplication] keyWindow];
    UIViewController *vc = window.rootViewController;
    [vc presentViewController:navi animated:YES completion:nil];
}

- (UINavigationController *)creatNaviWithRootController:(UIViewController *)viewController {
    UINavigationController *navi = [[UINavigationController alloc] initWithRootViewController:viewController];
    if (@available(iOS 15.0, *)) {
        UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];
        UIImage *navBgImg = [XLConversationInputView imageWithColor:[UIColor whiteColor] withFrame:CGRectMake(0, 0, 1, 1)];
        //设置导航栏背景颜色
        [appearance setBackgroundImage:navBgImg];
        [navi.navigationBar setScrollEdgeAppearance:appearance];
        [navi.navigationBar setStandardAppearance:appearance];
    }
    else {
        NSDictionary *dic = @{NSForegroundColorAttributeName : [UIColor blackColor],
                              NSFontAttributeName : [UIFont fontWithName:kXLCIPingFangSC_Medium size:18]};
        navi.navigationController.navigationBar.titleTextAttributes = dic;
        [navi.navigationBar setBackgroundImage:[XLConversationInputView imageWithColor:UIColor.whiteColor withFrame:CGRectMake(0, 0, 1, 1)] forBarMetrics:(UIBarMetricsDefault)];
    }
    //透明设置
    navi.navigationController.navigationBar.translucent = NO;
    navi.modalPresentationStyle = UIModalPresentationFullScreen;
    return navi;
}

- (BOOL)checkConversationInputViewProtocol
{
    if (self.delegate) {
        if ([self.delegate respondsToSelector:@selector(selectCompleteWithItem:andValue:)]) {
            return YES;
        }
        return NO;
    }
    return NO;
} 

- (void)processMessageString:(NSString *)message {
    if ([self checkConversationInputViewProtocol]) {
        [self.delegate selectCompleteWithItem:self.selectMoreItem andValue:message];
    }
}

+ (NSAttributedString *)replaceEmojiTextToEmojiImageWithText:(NSString *)message
{
    NSAttributedString *mutableString = [XLEmojiManager replaceEmojiTextToEmojiImageWithText:message];
    return mutableString;;
}

- (void)annalizJson {
    NSString *filePath = [[XLCIViewResourcesManager XLCIResourcesBundle] pathForResource:@"emoji" ofType:@"json"];
    NSData *jsonData = [NSData dataWithContentsOfFile:filePath];
    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
    NSMutableDictionary *mDict = [[NSMutableDictionary alloc] init];
    for (NSInteger index = 0; index < dict.allKeys.count; index++) {
        NSString *key = dict.allKeys[index];
        NSString *value = dict[key];
        NSString *string = [value stringByReplacingOccurrencesOfString:@"wx_emoji_" withString:@"wx_emoji_0"];
        mDict[key] = string;
    }
    for (NSString *item in mDict.allKeys) {
        NSString *value = mDict[item];
        printf("\"%s\":\"%s\",", [item UTF8String], [value UTF8String]);
    }
}

#pragma mark ------------------------- Other

- (void)dealloc
{
    [self reinit];
}

- (void)reinit
{
    [self.emojiInput removeFromSuperview];
    self.emojiInput = nil;
    [self.toolBar removeFromSuperview];
    self.toolBar = nil;
    [self.moreItemActionView removeFromSuperview];
    self.moreItemActionView = nil;
    [self.recoredPressView removeFromSuperview];
    self.recoredPressView = nil;
    self.moreItemViewHeight = 0;
    self.moreItemViewMinimumInteritemSpacingt = 0;
    self.delegate = nil;
}

#pragma mark Delegate

- (NSArray<XLCFileTypeKey> *)supportFileTypes
{
    NSArray<XLCFileTypeKey> *supportExten = nil;
    if (self.delegate && [self.delegate respondsToSelector:@selector(supportFileTypes)]) {
        supportExten = [self.delegate supportFileTypes];
    }
    return supportExten;
}

- (NSArray<NSString *> *)fileListDirectory
{
    if (self.delegate && [self.delegate respondsToSelector:@selector(fileListDirectory)]) {
        NSArray *array = [self.delegate fileListDirectory];
        return array;
    }
    return nil;
}
- (NSDictionary *)audioRecorderParameters
{
    NSDictionary  *parameters = nil;
    if (self.delegate && [self.delegate respondsToSelector:@selector(audioRecorderParameters)]) {
        parameters = [self.delegate audioRecorderParameters];
    }
    return parameters;
}
@end
